package com.javaDemo.thread;

import org.apache.commons.lang3.concurrent.BasicThreadFactory;

import java.util.concurrent.*;
import java.util.concurrent.Future;

public class CallBackTest {

    //org.apache.commons.lang3.concurrent.BasicThreadFactory



    // ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
    //         .setNameFormat("demo-pool-%d").build();
    //
    // //Common Thread Pool
    // ExecutorService threadPool = new ThreadPoolExecutor(5, 200,
    //         0L, TimeUnit.MILLISECONDS,
    //         new LinkedBlockingQueue<Runnable>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
    //
    // pool.execute(()-> System.out.println(Thread.currentThread().getName()));
    // pool.shutdown();//gracefully shutdown


    public static int count = 0;

    public static void main(String[] str) {
        ScheduledExecutorService threadPool = new ScheduledThreadPoolExecutor(1,
                new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").daemon(true).build());

        FutureTask task = new FutureTask(new CallBackTest().new Task());
        for (int i = 1; i <= 1000; i++) {
            threadPool.submit(task);
        }
        threadPool.shutdown();
        try {
            if (!threadPool.awaitTermination(10000, TimeUnit.MILLISECONDS)) {
                // 超时的时候向线程池中所有的线程发出中断(interrupted)。
                threadPool.shutdownNow();
            }
        } catch (InterruptedException e) {
            threadPool.shutdownNow();
        }
        System.out.println(Thread.currentThread().getName() + ":" + count);

        addCallback(task, new FutureCallback() {
            @Override
            public void onSuccess(Object result) {
                System.out.println("future callback result:" + result);
            }

            @Override
            public void onFailure(Throwable t) {
                System.out.println(t);
            }

        });
    }

    private static <V> void addCallback(Future future, FutureCallback callback) {
        V value = null;
        if (future.isDone()) {
            try {
                value = (V) future.get();
            } catch (InterruptedException e) {
                callback.onFailure(e.getCause());
            } catch (ExecutionException e) {
                callback.onFailure(e.getCause());
            }
            callback.onSuccess(value);
        }
    }

    public interface FutureCallback<V> {
        void onSuccess(V result);

        void onFailure(Throwable t);
    }

    public class Task implements Callable<Integer> {
        @Override
        public Integer call() {
            synchronized (this) {
                count++;
                System.out.println(Thread.currentThread().getName() + ":" + count);
                try {
                    Thread.sleep(3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return count;
        }

    }
}
